#pragma once
#include <mqcomm/Helper.hpp>
#include <mqcomm/Log.hpp>
#include <mqcomm/Message.pb.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <functional>
using namespace std;


namespace rbmq {
    // 消费者对象结构体
    typedef function<void(const string& tag, const mqNs::BasicProperties* bp, const string& msg_body)> consumerCallback;
    struct consumer {
        typedef shared_ptr<consumer> ptr;
        consumer() {}
        consumer(const string& tag, const string& qname, bool auto_ack, const consumerCallback& callback) 
            :_tag(tag)
            ,_qname(qname)
            ,_auto_ack(auto_ack)
            ,_callback(callback)
        {

        }
        string _tag; // 消费者标识
        string _qname; // 消费者订阅的队列名称
        bool _auto_ack; // 消费者是否自动确认
        consumerCallback _callback; // 消费者处理消息的回调函数
    };

    // 以队列为单元的消费者管理结构
    class QueueConsumer {
    public :
        typedef shared_ptr<QueueConsumer> ptr;
        QueueConsumer(const string& qname) 
            :_qname(qname)
            ,_rr_seq(0)
        {}
        
        // 向队列新增消费者
        consumer::ptr createConsumer(const string& tag, const string& qname, bool auto_ack, const consumerCallback& callback) {
            // 对消费者的访问也是可能在多执行留下执行的，所以也存在线程安全问题，所以要先枷锁
            unique_lock<mutex> lock(_mutex);
            // 先判断队列中是否有该消费者，如果已经有了几不用再创建了
            for (auto& consume : _consumers) {
                if (consume->_tag == tag) {
                    return consumer::ptr();
                }
            }
            // 没有重复则新增一个(构造对象)
            consumer::ptr newconsumer = make_shared<consumer>(tag, qname, auto_ack, callback);
            // 添加管理后，返回对象
            _consumers.push_back(newconsumer);
            return newconsumer;
        }
        // 从队列中删除一个消费者
        void removeConsumer(const string& tag) {
            unique_lock<mutex> lock(_mutex);
            for (auto it = _consumers.begin(); it != _consumers.end(); it++) {
                if ((*it)->_tag == tag) {
                    _consumers.erase(it);
                    return ;
                }
            }
        }
        // 获取一个消费者
        consumer::ptr chooseConsumer() {
            unique_lock<mutex> lock(_mutex);
            if (_consumers.size() == 0) {
                return consumer::ptr();
            }
            consumer::ptr ret = _consumers[_rr_seq];
            _rr_seq++;
            _rr_seq %= _consumers.size();
            return ret;
        }

        // 判断消费者队列是否为空
        bool empty() {
            unique_lock<mutex> lock(_mutex);
            return _consumers.empty();
        }

        // 判断队列里是否有指定的消费者
        bool exists(const string& tag) {
            unique_lock<mutex> lock(_mutex);
            if (_consumers.size() == 0) {
                return false;
            }
            for (auto consume : _consumers) {
                if (consume->_tag == tag) {
                    return true;
                }
            }
            return false;
        }

        // 清理所有的消费者
        void clear() {
            unique_lock<mutex> lock(_mutex);
            _consumers.clear();
            _rr_seq = 0;
        }
    private :
        string _qname; // 队列名称
        mutex _mutex; // 互斥锁
        uint64_t _rr_seq; // RR轮转序号
        vector<consumer::ptr> _consumers; // 消费者集合 
    };

    // 对外提供的消费者管理类
    class consumerManager {
    public :
        typedef shared_ptr<consumerManager> ptr;
        consumerManager(){}

        // 初始化一个队列消费者管理句柄
        void InitQueueConsumer(const string& qname) {
            // 1、加锁
            unique_lock<mutex> lock(_mutex);
            // 2、判断指定队列的句柄是否已经存在，如果已经存在就不需要再创建了
            auto it = _queue_consumers.find(qname);
            if (it != _queue_consumers.end()) {
                return;
            }
            // 3、创建句柄, 加入哈希表
            QueueConsumer::ptr qcp = make_shared<QueueConsumer>(qname);
            _queue_consumers.insert(make_pair(qname, qcp));
        }
        
        // 销毁一个队列消费者管理句柄
        void destroyQueueConsumer(const string& qname) {
            // 1、加锁
            unique_lock<mutex> lock(_mutex);
            // 2、直接erase
            _queue_consumers.erase(qname);
        }

        // 向指定队列新增消费者
        consumer::ptr createConsumer(const string& qname, const string& tag, bool auto_ack, const consumerCallback& callback) {
            QueueConsumer::ptr qcp;
            {
                // 1、加锁
                unique_lock<mutex> lock(_mutex);
                // 2、先判断制定队列的消费者管理句柄是否存在，如果不存在这不能新增
                auto it = _queue_consumers.find(qname);
                if (it == _queue_consumers.end()) {
                    LOG(Debug) << "向队列: " << qname << " 新增消费者失败: 没有找到对应的队列消费者管理句柄!" << endl;
                    return consumer::ptr();
                }
                qcp = it->second;
            }
            // 3、如果存在，则通过句柄新增
            return qcp->createConsumer(tag, qname, auto_ack, callback);
        }
        
        // 从指定队列中移除指定的一个消费者
        void removeQueueConsumer(const string& qname, const string& tag) {
            QueueConsumer::ptr qcp;
            {
                // 1、加锁
                unique_lock<mutex> lock(_mutex);
                // 2、先判断制定队列的消费者管理句柄是否存在，如果不存在这不能移除
                auto it = _queue_consumers.find(qname);
                if (it == _queue_consumers.end()) {
                    LOG(Debug) << "从队列: " << qname << " 移除消费者失败: 没有找到对应的队列消费者管理句柄!" << endl;
                }
                qcp = it->second;
            }
            qcp->removeConsumer(tag);
        }

        // 获取指定队列的一个消费者
        consumer::ptr choose(const string& qname) {
            QueueConsumer::ptr qcp;
            {
                // 1、加锁
                unique_lock<mutex> lock(_mutex);
                // 2、先判断制定队列的消费者管理句柄是否存在，如果不存在这不能获取
                auto it = _queue_consumers.find(qname);
                if (it == _queue_consumers.end()) {
                    LOG(Debug) << "从队列: " << qname << " 获取消费者失败: 没有找到对应的队列消费者管理句柄!" << endl;
                    return consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->chooseConsumer();
        }

        // 判断指定队列的消费者是否为空
        bool empty(const string& qname) {
            QueueConsumer::ptr qcp;
            {
                // 1、加锁
                unique_lock<mutex> lock(_mutex);
                // 2、先判断指定队列的消费者管理句柄是否存在，如果不存在这不能判断
                auto it = _queue_consumers.find(qname);
                if (it == _queue_consumers.end()) {
                    LOG(Debug) << "判断队列: " << qname << " 是否为空失败: 没有找到对应的队列消费者管理句柄!" << endl;
                    consumer::ptr();
                    return false;
                }
                qcp = it->second;
            }
            return qcp->empty();
        }

        // 判断制定队列里的指定一个消费者是否存在
        bool exists(const string& qname, const string& tag) {
            QueueConsumer::ptr qcp;
            {
                // 1、加锁
                unique_lock<mutex> lock(_mutex);
                // 2、先判断指定队列的消费者管理句柄是否存在，如果不存在这不能判断
                auto it = _queue_consumers.find(qname);
                if (it == _queue_consumers.end()) {
                    LOG(Debug) << "判断队列: " << qname << " 指定消费者是否存在失败: 没有找到对应的队列消费者管理句柄!" << endl;
                    return false;
                }
                qcp = it->second;
            }
            return qcp->exists(tag);
        }

        // 清理所有的队列即消费者
        void clear() {
            // 1、加锁
            unique_lock<mutex> lock(_mutex);
            // 2、遍历_queue_consumers，把每一个消费者队列管理句柄都清理一下
            for (auto it = _queue_consumers.begin(); it != _queue_consumers.end(); it++) {
                it->second->clear();
            }
            _queue_consumers.clear();
        }

    private :
        mutex _mutex;
        unordered_map<string, QueueConsumer::ptr> _queue_consumers; // 队列名称与队列消费者管理句柄的映射哈希表
    };
};